package org.ithasu.tools.data;

import org.ithasu.tools.net.JSONTools;
import org.ithasu.tools.net.JSONTools.JSONContext;
import org.ithasu.tools.net.JSONTools.JSONEntity;
import org.json.simple.JSONObject;

public class ERef<E extends Entity> implements JSONEntity {

	private final static String JSON_PROPERTY_PROVIDER = "provider";
	private final static String JSON_PROPERTY_ID = "id";

	private EntityProvider<E> provider;
	private Long id;

	// -- Constructor ----------------------------------------

	public ERef(ERef<E> ptr) {
		this.provider = ptr.provider;
		this.id = ptr.id;
	}

	public ERef(ERef<E> ptr, Long newIndex) {
		this.provider = ptr.provider;
		this.id = newIndex;
	}

	public ERef(EntityProvider<E> provider, E entity) {
		this.provider = provider;
		this.id = entity == null ? null : entity.getId();
	}

	public ERef(EntityProvider<E> provider, Long index) {
		this.provider = provider;
		this.id = index;
	}

	// -- Get ----------------------------------------

	public Long getIndex() {
		return id;
	}

	public E get() {
		if (id == null) {
			return null;
		} else {
			return provider.getEntityById(id);
		}
	}

	// -- Set ----------------------------------------

	public void set(E entity) {
		this.id = entity == null ? null : entity.getId();
	}

	public void set(Long index) {
		this.id = index;
	}

	// -- Tools ----------------------------------------

	/**
	 * @return true if get() will return a null value. Note that null may be
	 *         either valid or invalid.
	 */
	public boolean isNull() {
		return id == null || get() == null;
	}

	/**
	 * @return true if entity pointed by index exists or if index is null
	 */
	public boolean isValid() {
		return EntityTools.isValid(provider, id);
	}

	// -- JSON ----------------------------------------

	@SuppressWarnings("unchecked")
	@Override
	public JSONObject toJSON(JSONContext context) {
		JSONObject o = new JSONObject();
		o.put(JSON_PROPERTY_PROVIDER, context.getEntityProviderId(provider));
		o.put(JSON_PROPERTY_ID, id);
		return o;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void parseJSON(JSONContext context, JSONObject o) {
		String providerId = JSONTools.getProperty(String.class, o, JSON_PROPERTY_PROVIDER);
		if (providerId == null) {
			return;
		}
		EntityProvider<?> provider = context.getEntityProvider(providerId);
		if (provider == null) {
			return;
		}
		this.provider = (EntityProvider<E>) provider;
		this.id = JSONTools.getProperty(Long.class, o, JSON_PROPERTY_ID);
	}
}
